package com.faner.fast.upms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.faner.fast.exception.FailedException;
import com.faner.fast.file.FileConstant;
import com.faner.fast.file.FileProperties;
import com.faner.fast.file.Uploader;
import com.faner.fast.upms.mapper.FileMapper;
import com.faner.fast.upms.domain.bo.FileBO;
import com.faner.fast.upms.model.FileDO;
import com.faner.fast.upms.service.FileService;
import com.faner.fast.util.DateUtils;
import com.faner.fast.util.FileUtil;
import com.faner.fast.util.ScpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, FileDO> implements FileService {

    @Autowired
    private Uploader uploader;
    /**
     * {@link org.springframework.beans.factory.support.AbstractBeanFactory}
     * 文件上传配置信息
     */
    @Autowired
    private FileProperties fileProperties;
    @Value("${scp.ip:127.0.0.1}")
    private String ip;
    @Value("${scp.port:22}")
    private int port;
    @Value("${scp.username:root}")
    private String username;
    @Value("${scp.password:123456}")
    private String password;
    @Value("${scp.url}")
    private String url;
    @Value("${scp.dir:/root/pdf/}")
    private String dir;




    /**
     * 为什么不做批量插入
     * 1. 文件上传的数量一般不多，3个左右
     * 2. 批量插入不能得到数据的id字段，不利于直接返回数据
     * 3. 批量插入也仅仅只是一条sql语句的事情，如果真的需要，可以自行尝试一下
     */
    @Override
    public List<FileBO> upload(MultiValueMap<String, MultipartFile> fileMap) {
        List<FileBO> res = new ArrayList<>();
        uploader.upload(fileMap, file -> {
            FileDO found = this.baseMapper.selectByMd5(file.getMd5());
            // 数据库中不存在
            if (found == null) {
                FileDO fileDO = new FileDO();
                BeanUtil.copyProperties(file, fileDO);
                this.getBaseMapper().insert(fileDO);
                res.add(transformDoToBo(fileDO, file.getKey()));
                return true;
            }
//            // 已存在，则直接转化返回
            res.add(transformDoToBo(found, file.getKey()));
            return false;
        });
        return res;
    }

    @Override
    public boolean checkFileExistByMd5(String md5) {
        return this.getBaseMapper().selectCountByMd5(md5) > 0;
    }

    private FileBO transformDoToBo(FileDO file, String key) {
        FileBO bo = new FileBO();
        BeanUtil.copyProperties(file, bo);
        if (file.getType().equals(FileConstant.LOCAL)) {
            String s = fileProperties.getServePath().split("/")[0];
            // replaceAll 是将 windows 平台下的 \ 替换为 /
            if(System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS")){
                bo.setUrl(fileProperties.getDomain() + s + "/" + file.getPath().replaceAll("\\\\","/"));
            }else {
                bo.setUrl(fileProperties.getDomain() + s + "/" + file.getPath());
            }
        } else {
            bo.setUrl(file.getPath());
        }
        bo.setKey(key);
        return bo;
    }

    @Override
    public Boolean pdfCreate(String reportId, Integer uid){
//        String reportId = "37ca8617a73945d7ae8ddad7eddd854e";
//        Integer uid = 204;
        String fileName = DateUtils.coverLocalDateTimeToStr(LocalDateTime.now(),DateUtils.FULL_TIME_PATTERN)+"-"+reportId+"-"+uid;
        File dire = new File(dir);
        if(!dire.exists()){
            dire.mkdirs();
        }
        ScpClientUtil scpClientUtil = ScpClientUtil.getInstance(ip, port, username, password);
        String script = "node /root/node/test3.js "+ url +"/"+reportId+"/"+uid+ " " +fileName + " " + dir;
        try {
            ScpClientUtil.ShellResult exec = scpClientUtil.exec(script, StandardCharsets.UTF_8);
            log.info(">>>>>>Result>>>>>>>");
            log.info(exec.getResult());
            log.info(">>>>>>ErrorMsg>>>>>>>>");
            log.info(exec.getErrorMsg());
        }catch (IOException e){
            throw new FailedException(e.getMessage());
        }
        String name =dir+fileName+".pdf";
        //校验文件是否存在
        boolean exists = FileUtil.exists(name);
        if (exists){
            MultiValueMap<String, MultipartFile> o1 = new LinkedMultiValueMap<String, MultipartFile>();
            //上传oss
            MultipartFile file = new MockMultipartFile(name,name, MediaType.MULTIPART_FORM_DATA_VALUE, FileUtil.getByte(new File(name)));
            o1.add("file",file);
            List<FileBO> uploadList = upload(o1);
            //删除文件
            FileUtil.deleteFile(name);
            if (CollectionUtil.isEmpty(uploadList)){
                return false;
            }
            //发送邮件发送链接删除后操作即可 发送文件需要在删除前操作 比较耗费服务器资源 建议发送链接
            return  true;
        }
        return false;
    }

}
